package twentyone;

import java.util.ArrayList;
import java.util.Scanner;

public class 运动会 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        // 读取每个员工的权重
        int[] weight = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            weight[i] = sc.nextInt();
        }
        
        // 构建树结构（邻接表），添加泛型类型安全转换
        @SuppressWarnings("unchecked")
        ArrayList<Integer>[] tree = new ArrayList[n + 1];
        for (int i = 0; i <= n; i++) {
            tree[i] = new ArrayList<>();
        }
        
        // 直接记录每个节点的父节点，用于找根
        int[] parent = new int[n + 1];
        
        // 读取员工的领导关系，正确构建树：Y是X的领导，X是Y的子节点
        for (int i = 0; i < n - 1; i++) {
            int child = sc.nextInt();  // 员工X
            int leader = sc.nextInt(); // 领导Y
            tree[leader].add(child);   // 领导Y的下属是员工X
            parent[child] = leader;    // 记录员工X的领导是Y
        }
        
        // 找到根节点（没有领导的员工）
        int root = 0;
        for (int i = 1; i <= n; i++) {
            if (parent[i] == 0) {
                root = i;
                break;
            }
        }
        
        // 动态规划求解
        int[][] dp = new int[n + 1][2];
        dfs(root, tree, weight, dp);
        
        // 输出结果
        System.out.println(Math.max(dp[root][0], dp[root][1]));
        sc.close();
    }
    
    // 树形DP
    private static void dfs(int node, ArrayList<Integer>[] tree, int[] weight, int[][] dp) {
        // dp[node][0]表示不选择node时的最大权重和
        // dp[node][1]表示选择node时的最大权重和
        
        dp[node][1] = weight[node]; // 选择当前节点
        
        for (int child : tree[node]) {
            dfs(child, tree, weight, dp);
            dp[node][0] += Math.max(dp[child][0], dp[child][1]); // 不选当前节点，子节点可选可不选
            dp[node][1] += dp[child][0]; // 选择当前节点，子节点不能选
        }
    }
}
